﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://www.codeplex.com/EmlenMud
using System.Text;
using System.Runtime.Serialization;
using System;
using System.Threading;
using System.ComponentModel;
using System.Collections;
using System.Collections.Generic;
using BrainTechLLC.ThreadSafeObjects;
using WordsMatching;
using System.Xml.Serialization;
#if USE_HYPER
using Hyper.ComponentModel;
#endif

namespace BrainTechLLC
{
#if NO_SILVERLIGHT
    [EditorBrowsable(EditorBrowsableState.Always)]
#endif
    [Serializable]
    [DataContract]
    public class NameAndDescription : INameAndDescription, IFormattable, INotifyPropertyChanged, INotifyPropertyChanging
    {
        public NameAndDescription() { }

        [DataMember]
        public string _friendlyUniqueName;

        [XmlIgnore]
        public string FriendlyUniqueName
        {
            get { return _friendlyUniqueName; }
            set
            {
                if (!_friendlyUniqueName.AreEqual(value))
                {
                    OnPropertyChanging("FriendlyUniqueName", _friendlyUniqueName, value);
                    _friendlyUniqueName = value;
                    OnPropertyChanged("FriendlyUniqueName", _friendlyUniqueName, value);
                }
            }
        }

        public NameAndDescription CreateCopy()
        {
            NameAndDescription result = new NameAndDescription()
            {
                _description = this._description,
                _friendlyUniqueName = this._friendlyUniqueName,
                _keywords = this._keywords,
                _name = this._name,
                _oneLineDescription = this._oneLineDescription,
                _shortDescription = this._shortDescription
            };

            return result;
        }

#if NO_SILVERLIGHT
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
#endif
        [XmlIgnore]
        public string[] SeparateKeywords
        {
            get
            {
                if (string.IsNullOrEmpty(Keywords))
                {
                    return new string[1] { string.Empty };
                }
                return Keywords.Split('~');
            }
        }

        public float KeywordMatchStrength(string matchString, out string bestMatch)
        {
            if (string.IsNullOrEmpty(matchString))
            {
                bestMatch = string.Empty;
                return 1.0f;
            }
            return SeparateKeywords.KeywordMatchStrength(matchString, out bestMatch);
        }

        [DataMember]
        public string _name;

        [XmlIgnore]
        public string Name
        {
            get { return _name; }
            set
            {
                if (!_name.AreEqual(value))
                {
                    OnPropertyChanging("Name", _name, value);
                    _name = value;
                    OnPropertyChanged("Name", _name, value);
                }
            }
        }

        [DataMember]
        public string _shortDescription;

        [XmlIgnore]
        public string ShortDescription
        {
            get { return _shortDescription; }
            set
            {
                if (!_shortDescription.AreEqual(value))
                {
                    OnPropertyChanging("ShortDescription", _shortDescription, value);
                    _shortDescription = value;
                    OnPropertyChanged("ShortDescription", _shortDescription, value);
                }
            }
        }

        [DataMember]
        public string _description;

        [XmlIgnore]
        public string Description
        {
            get { return _description; }
            set
            {
                if (!_description.AreEqual(value))
                {
                    OnPropertyChanging("Description", _description, value);
                    _description = value;
                    OnPropertyChanged("Description", _description, value);
                }
            }
        }

        [DataMember]
        public string _oneLineDescription;

        [XmlIgnore]
        public string OneLineDescription
        {
            get
            {
                return _oneLineDescription;
            }
            set
            {
                if (!_oneLineDescription.AreEqual(value))
                {
                    OnPropertyChanging("OneLineDescription", _oneLineDescription, value);
                    _oneLineDescription = value;
                    OnPropertyChanged("OneLineDescription", _oneLineDescription, value);
                }
            }
        }

        [DataMember]
        public string _keywords;

        [XmlIgnore]
        public string Keywords
        {
            get
            {
                return _keywords;
            }
            set
            {
                if (!_keywords.AreEqual(value))
                {
                    OnPropertyChanging("Keywords", _keywords, value);
                    _keywords = value;
                    OnPropertyChanged("Keywords", _keywords, value);
                }
            }
        }

        public virtual void OnPropertyChanged(string property, object oldValue, object newValue)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgsEx(property) { OldValue = oldValue, NewValue = newValue });
            }
        }

        public virtual void OnPropertyChanging(string property, object oldValue, object newValue)
        {
            if (PropertyChanging != null)
            {
                PropertyChanging(this, new PropertyChangingEventArgsEx(property) { OldValue = oldValue, NewValue = newValue });
            }
        }

        public virtual void OnPropertyChanged(object sender, PropertyChangedEventArgsEx args)
        {
            if (PropertyChanged != null)
            {
                args.ChildObject = sender;
                PropertyChanged(this, args);
            }
        }

        public virtual void OnPropertyChanging(object sender, PropertyChangingEventArgsEx args)
        {
            if (PropertyChanging != null)
            {
                args.ChildObject = sender;
                PropertyChanging(this, args);
            }
        }

        #region INotifyPropertyChanged Members

        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region INotifyPropertyChanging Members

#if NO_SILVERLIGHT
        [field: NonSerialized]
        public event PropertyChangingEventHandler PropertyChanging;
#else
        [field: NonSerialized]
        public event EventHandler<PropertyChangingEventArgsEx> PropertyChanging;
#endif

        #endregion

        public override string ToString()
        {
            if (string.IsNullOrEmpty(ShortDescription))
            {
                return Name + " is here";
            }
            else
            {
                return ShortDescription;
            }
            //StringBuilder sb = new StringBuilder();
            //sb.AppendLine(Name);
            //sb.AppendLine(Keywords);
            //sb.AppendLine(ShortDescription);
            //sb.AppendLine(OneLineDescription);
            //return sb.ToString();
        }

        #region IFormattable Members

        public string ToString(string format, IFormatProvider formatProvider)
        {
            return ToString();
        }

        #endregion
    }

    public static class ExtKW
    {
        public static float PercentInCommon(string matchString, string s2)
        {
            if (matchString.Equals(s2, StringComparison.OrdinalIgnoreCase))
                return 1.0f;

            int l1 = matchString.Length;
            int l2 = s2.Length;
            int min = l1 < l2 ? l1 : l2;
            int cnt = 0;

            for (int n = 0; n < min; n++)
            {
                if (s2.Contains(matchString[n].ToString()))
                    cnt++;
            }

            return (float)((float)cnt / (float)l2);
        }

        public static float KeywordMatchStrength(this IEnumerable<string> strings, string matchString, out string bestMatch)
        {
            bestMatch = string.Empty;
            float bestMatchWeight = 0.0f;
            foreach (string s in strings)
            {
                float pct = PercentInCommon(matchString, s);
                if (pct == 1.0f)
                {
                    bestMatch = s;
                    return 1.0f;
                }
                else if (pct > 0.5f)
                {
                    MatchsMaker m = new MatchsMaker(matchString, s);
                    float f = m.Score;
                    if (f > bestMatchWeight)
                    {
                        bestMatchWeight = f;
                        bestMatch = s;
                    }
                }
            }
            return bestMatchWeight;
        }

        public static Type GetType(this string typeName, Type defaultType, bool throwOnMissing)
        {
            if (string.IsNullOrEmpty(typeName))
                return defaultType;

            Type t = TypeProvider.GetInstance().GetType(typeName);

            if (t == null && throwOnMissing)
                throw new Exception(String.Format("Type name {0} not found", typeName));

            return t;
        }
    }

    public class DoNotWriteBackAttribute : Attribute, IReadableAttribute
    {
        public bool NoWriteback { get; set; }
        public DoNotWriteBackAttribute() { NoWriteback = true; }
        public DoNotWriteBackAttribute(bool val) { NoWriteback = val; }

        public object Value
        {
            get { return NoWriteback; }
        }
    }

}